package com.idc.common.util;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

import javax.annotation.PostConstruct;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import com.idc.common.config.AppConfig;
import com.idc.common.constant.EncryptionConstant;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Configuration
public class AES {

	@Autowired
	private AppConfig appConfig;

	private static int length = 128;
	private static final String AES_SECRET_KEY = "WsKAoGweOXQdMXp1BfU93odl8+S/fTu8zeV8n5z9VEvtkEfs3wjMqpTzfSr8gOBPTShCUx5uiPb68g1jxQO1k/CP4OJ6BBUwMCuAxTT/Ro/UKdrVjfV/0TXBu" +
			"MkUL2fH4tvDkyy68QxneJ1cad5AlX95Jp2aIZnWBv8kQBq6La4SWUr8o1TocmnPIRRrWr/FQDWlUylfRcn4SD7F5BZEc5X" +
			"Myp4Rc/n19ygsAn6d6nyGSvTJGjp9OsZdQIw8Oo2pM0ujgXmx54LHS1NwoXRmfsvShnb5FOwLTEs8nHQZ1f" +
			"HTtorIlkzM+69gqU15pxKQ5kyERXfMR+SOVdS8HVrkK1shqBNRzX7yZExA3WuUe7vO2jNJFy4fxtaTvgCo1PEE2Znct3Xl" +
			"av/JFXh+yuw9cfFcSnTc1YOO8FRdPe6L+IhPbAnm/bzCcoDQUa3uROdL" +
			"y8he57hSkXqYddy63WUzNIg06nUlRfUZeAOsA6Mj1gj4jSPv/5tnovboaWN/0IhR";

	private static cn.hutool.crypto.symmetric.AES appAes;

	public static cn.hutool.crypto.symmetric.AES getAppAes() {
		return appAes;
	}

	public static void setAppAes(cn.hutool.crypto.symmetric.AES appAes) {
		AES.appAes = appAes;
	}

	public static void refreshAppSecretKey(String appAesSecretKey) {
		LogUtil.info(log, "AES refreshAppSecretKey {}", appAesSecretKey);
		setAppAes(new cn.hutool.crypto.symmetric.AES(appAesSecretKey.getBytes(StandardCharsets.UTF_8)));
	}

	@PostConstruct
	public void init() {
		LogUtil.info(log, "AesConfig init");
		String appAesSecretKey = appConfig.getConfig().getAppAesSecretKey();
		appAes = new cn.hutool.crypto.symmetric.AES(appAesSecretKey.getBytes(StandardCharsets.UTF_8));
	}


	/**
	 * 加密
	 *
	 * @param content
	 *            需要加密的内容
	 * @param aseKay
	 *            加密密码
	 * @return
	 */
	private static byte[] encrypt(String content, String aseKay) {
		try {
			KeyGenerator kgen = KeyGenerator.getInstance(EncryptionConstant.AES_CONSTANT);
			SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
			secureRandom.setSeed(aseKay.getBytes());
			kgen.init(length, secureRandom);
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec key = new SecretKeySpec(enCodeFormat, EncryptionConstant.AES_CONSTANT);
			Cipher cipher = Cipher.getInstance(EncryptionConstant.AES_CONSTANT);// 创建密码器
			byte[] byteContent = content.getBytes("utf-8");
			cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
			byte[] result = cipher.doFinal(byteContent);
			return result; // 加密
		} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | UnsupportedEncodingException | IllegalBlockSizeException | BadPaddingException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	  * @Title: decrypt
	  * @Description: 解密
	  * @param @param content
	  * @param @param aseKay
	  * @param @return    
	  * @return byte[]    
	 */
	private static byte[] decrypt(byte[] content, String aseKay) {
		try {
			KeyGenerator kgen = KeyGenerator.getInstance(EncryptionConstant.AES_CONSTANT);
			SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
			secureRandom.setSeed(aseKay.getBytes());
			kgen.init(length, secureRandom);
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec key = new SecretKeySpec(enCodeFormat, EncryptionConstant.AES_CONSTANT);
			Cipher cipher = Cipher.getInstance(EncryptionConstant.AES_CONSTANT);// 创建密码器
			cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
			byte[] result = cipher.doFinal(content);
			return result; // 加密
		} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException e) {
			throw new RuntimeException(e);
		}
	}
	public static String encrypt2Str(String content, String aseKay) {
		byte[] encryptResult = encrypt(content, aseKay);
		return Base64.getEncoder().encodeToString(encryptResult);
	}

	public static String decrypt2Str(String content, String aseKay) {
		byte[] decryptResult = decrypt(Base64.getDecoder().decode(content), aseKay);
		return StringUtils.newStringUtf8(decryptResult);
	}

	public static String encode(String content) {
		return encrypt2Str(content, AES_SECRET_KEY);
	}

	public static String decode(String content) {
		return decrypt2Str(content, AES_SECRET_KEY);
	}

	// app端aes加密方法，128位秘钥，秘钥配置为固定16位，默认秘钥从nacos获取

	public static String encryptForApp(String content) {
		return appAes.encryptBase64(content);
	}

	public static String decryptForApp(String content) {
		return appAes.decryptStr(content);
	}

	public static String encryptForApp(String content, String secretKey) {
		return new cn.hutool.crypto.symmetric.AES(secretKey.getBytes(StandardCharsets.UTF_8)).encryptBase64(content);
	}

	public static String decryptForApp(String content, String secretKey) {
		return new cn.hutool.crypto.symmetric.AES(secretKey.getBytes(StandardCharsets.UTF_8)).decryptStr(content);
	}

	public static String encryptForApp(cn.hutool.crypto.symmetric.AES appAesNew, String content) {
		return appAesNew.encryptBase64(content);
	}

	public static String decryptForApp(cn.hutool.crypto.symmetric.AES appAesNew, String content) {
		return appAesNew.decryptStr(content);
	}
}
